#include <LLIIO/PNGImage.h>

PNGImage::PNGImage()
{
}

PNGImage::~PNGImage()
{
}

bool PNGImage::Open( const char * szPath )
{
    bool bRet = false ;

    try
    {
        m_pContext.reset( new Context ) ;

        m_pContext->m_pFile = fopen( szPath , "rb" ) ;
        if ( m_pContext->m_pFile )
        {
            png_byte aHeader[8];
            if ( fread( aHeader , 1 , sizeof( aHeader ), m_pContext->m_pFile ) )
            {
                if ( ! png_sig_cmp( aHeader , 0 ,sizeof( aHeader ) ) )
                {
                    m_pContext->m_pReadStruct = png_create_read_struct( PNG_LIBPNG_VER_STRING , NULL , NULL , NULL ) ;
                    if ( m_pContext->m_pReadStruct )
                    {
                        m_pContext->m_pReadInfo = png_create_info_struct( m_pContext->m_pReadStruct ) ;
                        if ( m_pContext->m_pReadInfo )
                        {
                            png_init_io( m_pContext->m_pReadStruct , m_pContext->m_pFile ) ;
                            png_set_sig_bytes( m_pContext->m_pReadStruct , 8 ) ;
                            png_read_info( m_pContext->m_pReadStruct , m_pContext->m_pReadInfo ) ;

                            bRet = true ;
                        }
                    }
                }
            }
        }
    }
    catch( ... )
    {
    }

    if ( ! bRet )
    {
        Close() ;
    }

    return bRet ;
}

int PNGImage::GetWidth() const
{
    int iRet = 0 ;

    if ( m_pContext )
    {
        if ( m_pContext->m_pReadStruct )
        {
            iRet = png_get_image_width( m_pContext->m_pReadStruct , m_pContext->m_pReadInfo ) ;
        }
        else if ( m_pContext->m_pWriteStruct )
        {
            iRet = png_get_image_width( m_pContext->m_pWriteStruct , m_pContext->m_pWriteInfo ) ;
        }
    }

    return iRet ;
}

int PNGImage::GetHeight() const
{
    int iRet = 0 ;

    if ( m_pContext )
    {
        if ( m_pContext->m_pReadStruct )
        {
            iRet = png_get_image_height( m_pContext->m_pReadStruct , m_pContext->m_pReadInfo ) ;
        }
        else if ( m_pContext->m_pWriteStruct )
        {
            iRet = png_get_image_height( m_pContext->m_pWriteStruct , m_pContext->m_pWriteInfo ) ;
        }
    }

    return iRet ;
}

void PNGImage::Close()
{
    m_pContext.reset() ;
}

PNGImage::Context::Context()
    :
    m_pFile( NULL ) ,
    m_pReadStruct( NULL ) ,
    m_pReadInfo( NULL ) ,
    m_pWriteStruct( NULL ) ,
    m_pWriteInfo( NULL )
{
}

PNGImage::Context::~Context()
{
    if ( m_pFile )
    {
        fclose( m_pFile ) ;
    }

    if ( m_pReadStruct )
    {
        png_destroy_read_struct( & m_pReadStruct , & m_pReadInfo , NULL ) ;

        m_pReadStruct = NULL ;
        m_pReadInfo = NULL ;
    }
    else if ( m_pWriteStruct )
    {
        png_destroy_write_struct( & m_pWriteStruct , & m_pWriteInfo ) ;

        m_pWriteStruct = NULL ;
        m_pWriteInfo = NULL ;
    }
}
